package com.hy.jdbc.impl;

import com.hy.entity.Entity;
import org.apache.commons.lang.StringUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MysqlDatabase extends AbstractDatabase {

	@Override
	public List<String> getTablesByDatabase(Map<String, String> xmlMap){
		//jdbc参数
		String driverClass = xmlMap.get("driverClass");
		String url = xmlMap.get("url");
		String username = xmlMap.get("username");
		String password = xmlMap.get("password");
		//库名
		String database = xmlMap.get("database");

		Connection conn = AbstractDatabase.getConnection(driverClass, url, username, password);
		PreparedStatement ps = null;
		ResultSet rs = null;

		String SQL_TABLE_INFO = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = \"" + database + "\"";
		List<String> tables = new ArrayList<>();
		try {
			ps = conn.prepareStatement(SQL_TABLE_INFO);
			rs = ps.executeQuery();
			while(rs.next()){
				String tableName = rs.getString("TABLE_NAME");
				if(StringUtils.isNotEmpty(tableName)){
					tables.add(tableName);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			AbstractDatabase.close(rs, ps, conn);
		}
		return tables;
	}

	@Override
	public String getTableCommentInfo(Map<String, Object> xmlMap) {
		//jdbc参数
		String driverClass = xmlMap.get("driverClass").toString();
		String url = xmlMap.get("url").toString();
		String username = xmlMap.get("username").toString();
		String password = xmlMap.get("password").toString();
		//库名
		String database = xmlMap.get("database").toString();
		String tableName = xmlMap.get("tableName").toString();

		Connection conn = AbstractDatabase.getConnection(driverClass, url, username, password);
		PreparedStatement ps = null;
		ResultSet rs = null;

		String SQL_TABLE_COMMENT_INFO = "SELECT TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES " +
				"WHERE table_name=\""+tableName+"\" and table_schema = \"" + database + "\"";
		try {
			ps = conn.prepareStatement(SQL_TABLE_COMMENT_INFO);
			rs = ps.executeQuery();
			return rs.next() ? rs.getString("TABLE_COMMENT") : "";
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			AbstractDatabase.close(rs, ps, conn);
		}

		return "";
	}

	@Override
	public List<Entity> getEntityObjList(Map<String, Object> xmlMap) {
		//jdbc参数
		String driverClass = xmlMap.get("driverClass").toString();
		String url = xmlMap.get("url").toString();
		String username = xmlMap.get("username").toString();
		String password = xmlMap.get("password").toString();
		//库名
		String database = xmlMap.get("database").toString();
		String tableName = xmlMap.get("tableName").toString();

		//是否把下划线变为首字母大写，默认为true
		boolean isUpperCase = xmlMap.containsKey("isUpperCase") ? Boolean.parseBoolean(xmlMap.get("isUpperCase").toString()) : true;

		Connection conn = AbstractDatabase.getConnection(driverClass, url, username, password);

		PreparedStatement ps = null;
		ResultSet rs = null;

		String SQL_COLUMN_NAME = "SELECT COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT,COLUMN_KEY FROM INFORMATION_SCHEMA.Columns " +
				"WHERE table_name=\""+tableName+"\" and table_schema = \"" + database + "\"";
		List<Entity> entityList = new ArrayList<>();
		try {
			ps = conn.prepareStatement(SQL_COLUMN_NAME);
			rs = ps.executeQuery();
			while(rs.next()){

				String columnName = rs.getString("COLUMN_NAME");
				String columnType = rs.getString("DATA_TYPE");
				String columnComment = rs.getString("COLUMN_COMMENT");

				//主键处理
				String columnKey = rs.getString("COLUMN_KEY");
				if("PRI".equals(columnKey)){
					xmlMap.put("pkName", columnName);
				}
				if(columnName!=null && columnName.length()>1){
					xmlMap.put("pkNameUpcase", columnName.substring(0, 1).toUpperCase() + columnName.substring(1));
				}

				//赋值Entity
				Entity entity = new Entity();
				entity.setColumnName(columnName);
				entity.setColumnType(columnType);
				entity.setColumnComment(columnComment);

				//java属性名
				String javaProperty = "";
				if (isUpperCase && columnName.contains("_")) { //下划线改为首字母大写
					String columnNameStr[] = columnName.split("_");
					StringBuffer sb = new StringBuffer();
					for (int i = 0; i < columnNameStr.length; i++) {
						if (i == 0) {
							sb.append(columnNameStr[i].toLowerCase());
						} else {
							String str = columnNameStr[i].toLowerCase();
							if (str.length() > 1) {
								String beginStr = str.substring(0, 1);
								sb.append(beginStr.toUpperCase()).append(str.substring(1));
							} else {
								sb.append(str);
							}
						}
					}
					javaProperty = sb.toString();
				} else { //保留下划线
					javaProperty = columnName.toLowerCase();
				}
				entity.setJavaProperty(javaProperty);

				//java属性类型
				String javaType = "";
				// todo.. 可优化
				if(("int").equals(columnType) || ("mediumint").equals(columnType)
						|| ("smallint").equals(columnType) || ("tinyint").equals(columnType)){
					javaType = "Integer";
				}else if("bigint".equals(columnType)){
					javaType = "Long";
				}else if("varchar".equals(columnType) || "char".equals(columnType)){
					javaType = "String";
				}else if("decimal".equals(columnType)){
					javaType = "BigDecimal";
				}else if("float".equals(columnType)){
					javaType = "Float";
				}else if("double".equals(columnType)){
					javaType = "Double";
				}else if("tinytext".equals(columnType) || "text".equals(columnType)
						|| "mediumtext".equals(columnType) || "longtext".equals(columnType)){
					javaType = "String";
				}else if("datetime".equals(columnType)){
//					javaType = "Date";
					javaType = "LocalDateTime";
				}else if("timestamp".equals(columnType)){
					javaType = "Date";
				}else if("date".equals(columnType)){
//					javaType = "Date";
					javaType = "LocalDate";
				}else if("time".equals(columnType)){
//					javaType = "Date";
					javaType = "LocalTime";
				}else if("bit".equals(columnType)){
					javaType = "boolean";
				}
				entity.setJavaType(javaType);

				//方法名
				String methodName = javaProperty.substring(0, 1).toUpperCase() + javaProperty.substring(1);
				entity.setMethodName(methodName);

				entityList.add(entity);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			AbstractDatabase.close(rs, ps, conn);
		}
		return entityList;
    }

}
